TO CHECK WHO HAS UNSUBSCRIBED

SELECT email, full_name, date_added FROM crm_contacts WHERE unsubscribed = 1;


To Create a new campaign###

curl -s -X POST https://clarity-crm-api-layer.clarityawarenesscoaching.workers.dev/api/campaigns
-H "Content-Type: application/json"
-d '{"name":"Campaign Name","goal":"What you want to achieve"}'

Save the id returned — you need it for sequences and enrollment.


WRITE EMAIL STEPS

delay_days is days after the previous step. Step 1 = 0 sends immediately on enrollment. Step 2 = 3 sends 3 days after step 1. Available placeholders: , , , , .###

curl -s -X POST https://clarity-crm-api-layer.clarityawarenesscoaching.workers.dev/api/sequences
-H "Content-Type: application/json"
-d '{ "campaign_id":"CAMPAIGN_ID", "step_number":1, "delay_days":0, "subject":"Your subject", "body":"

Hi ,

Your message.

<a href="">Unsubscribe

", "from_name":"Lovinia Mak", "from_address":"courses@claritysystems.work" }'


ENROLL CONTACT ### Idempotent — safe to run twice, won't double-enroll.

curl -s -X POST https://clarity-crm-api-layer.clarityawarenesscoaching.workers.dev/api/enroll
-H "Content-Type: application/json"
-d '{"contact_id":"CONTACT_ID","campaign_id":"CAMPAIGN_ID"}'


CHECKING EMAIL STATUS

SELECT c.email, c.full_name, e.event_type, e.event_time FROM crm_email_events e JOIN crm_contacts c ON c.id = e.contact_id ORDER BY e.event_time DESC LIMIT 20;


Good — pipeline is end-to-end verified. Let me walk you through how to operate it.


How the pipeline works operationally

1. Add contacts

Currently manual via API. From your terminal:

curl -s -X POST https://clarity-crm-api-layer.clarityawarenesscoaching.workers.dev/api/contacts \
  -H "Content-Type: application/json" \
  -d '{"email":"person@company.com","full_name":"First Last","company":"Company Name"}'

CSV import is not built yet — that's next phase.


2. Create a campaign

curl -s -X POST https://clarity-crm-api-layer.clarityawarenesscoaching.workers.dev/api/campaigns \
  -H "Content-Type: application/json" \
  -d '{"name":"Campaign Name","goal":"What you want to achieve"}'

Save the id returned — you need it for sequences and enrollment.


3. Write email steps

curl -s -X POST https://clarity-crm-api-layer.clarityawarenesscoaching.workers.dev/api/sequences \
  -H "Content-Type: application/json" \
  -d '{
    "campaign_id":"CAMPAIGN_ID",
    "step_number":1,
    "delay_days":0,
    "subject":"Your subject",
    "body":"<p>Hi ,</p><p>Your message.</p><p><a href=\"\">Unsubscribe</a></p>",
    "from_name":"Lovinia Mak",
    "from_address":"courses@claritysystems.work"
  }'

delay_days is days after the previous step. Step 1 = 0 sends immediately on enrollment. Step 2 = 3 sends 3 days after step 1.

Available placeholders: , , , , ``.


4. Enroll a contact

curl -s -X POST https://clarity-crm-api-layer.clarityawarenesscoaching.workers.dev/api/enroll \
  -H "Content-Type: application/json" \
  -d '{"contact_id":"CONTACT_ID","campaign_id":"CAMPAIGN_ID"}'

Idempotent — safe to run twice, won't double-enroll.


5. Check email status

In D1 Console:

SELECT c.email, c.full_name, e.event_type, e.event_time
FROM crm_email_events e
JOIN crm_contacts c ON c.id = e.contact_id
ORDER BY e.event_time DESC LIMIT 20;

Unsubscribe — what happens

Yes, it updates your database. When someone clicks unsubscribe, the api-layer sets unsubscribed = 1 on that contact in crm_contacts. The sequence runner checks unsubscribed = 0 before every send — that contact will never receive another email from any campaign, permanently.

To check who has unsubscribed:

SELECT email, full_name, date_added FROM crm_contacts WHERE unsubscribed = 1;

What's not built yet that you'll need

Gap Impact
CSV import You can't load contacts at scale without it
Admin dashboard All of the above requires terminal curl commands right now
Reply ingestion Replies aren't logged to D1 yet

CSV import is the most pressing — you shouldn't be adding real contacts one by one. Want to build that next?